import http from 'http';
import https from 'https';
import { ServerOptions as HttpServerOptions } from 'https';
import proxy from './proxy';
import { colorText, getLocalhost } from './utils';
import { localProxy, staticSource } from './static';
import { ServerOptions } from '../index';

// 配置自签证书
const options: HttpServerOptions = {
	key: require('./cert/key'),
	cert: require('./cert/cert'),
};

const server = (props?: ServerOptions) => {
	const useHttps = props?.https || false;
	const host = '0.0.0.0';
	const port = props?.port || 3000;
	const proxyTable = props?.proxyTable || [];
	const outputPath = props?.outputPath;

	const requester = useHttps ? https : http;

	// 创建http/https服务器
	// @ts-ignore
	const httpServer = requester.createServer(options, (req, res) => {
		const option = proxy({
			req,
			proxyTable,
			https: useHttps,
			host,
			port,
		});

		// 为了不陷入请求本身的死循环，处理请求本地资源
		if (outputPath && option.hostname === host && option.port === port) {
			staticSource(res, outputPath, option.path as string);
			return;
		}

		// 代理请求本地目录下资源
		if (option.host === 'local' && option.port === 'local') {
			localProxy(res, option.path as string);
			return;
		}

		const proxyRequester = { 'http:': http, 'https:': https }[option.protocol!];
		const proxyReq = proxyRequester!.request(option, (proxyRes) => {
			if (proxyRes.statusCode === 404 && outputPath) {
				// 404转向请求本地资源，前端路由转由index.html处理
				staticSource(res, outputPath, option.path as string);
				return;
			}
			// 将目标服务器的响应头写入客户端响应
			res.writeHead(proxyRes.statusCode || 200, proxyRes.headers);
			// 将目标服务器的响应数据写入客户端响应
			proxyRes.pipe(res, { end: true });
		});

		// 将客户端的请求数据写入目标服务器请求
		req.pipe(proxyReq, { end: true });
	});

	httpServer.listen(port, () => {
		const ip = getLocalhost();
		const prefix = colorText(' Done ', 'white', 'green');
		const text = colorText(`server is running on ${useHttps ? 'https' : 'http'}://${ip}:${port}`, 'blue');
		console.log(`${prefix} ${text}`);
	});

	// 监听error事件
	httpServer.on('error', (err: any) => {
		if (err.code === 'EADDRINUSE') {
			server({
				https: useHttps,
				port: port + 1,
				proxyTable,
			});
		} else {
			const prefix = colorText(' Done ', 'white', 'red');
			const text = colorText(err.message, 'red');
			console.log(`${prefix} ${text}`);
		}
	});
};

export default server;
